#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // init
    number_system_ = NUMBERSYSTEM_UNDEFINE;

    connect(ui->checkBox_OtherNumberSystem,&QCheckBox::clicked,this,&MainWindow::check_OtherNumberSystem);

    connect(ui->lineEdit_Input,&QLineEdit::textChanged,this,&MainWindow::edit_Input);

    connect(ui->Button_StartTransfer,&QPushButton::pressed,this,&MainWindow::button_StartTransfer);
}

MainWindow::~MainWindow()
{
    delete ui;
}

int MainWindow::get_NumberSystem() {
    if (ui->rButton_Bin->isChecked()) {
        number_system_=NUMBERSYSTEM_BIN;
        return NUMBERSYSTEM_BIN;
    }
    else if (ui->rButton_Oct->isChecked()) {
        number_system_ = NUMBERSYSTEM_OCT;
        return NUMBERSYSTEM_OCT;
    }
    if (ui->rButton_Dec->isChecked()) {
        number_system_ = NUMBERSYSTEM_DEC;
        return NUMBERSYSTEM_DEC;
    }
    if (ui->rButton_Hex->isChecked()) {
        number_system_ = NUMBERSYSTEM_HEX;
        return NUMBERSYSTEM_HEX;
    }
    return -1;
}

void MainWindow::check_OtherNumberSystem(bool checked) {
    if (checked) {
        ui->Edit_InputNumberSystem->setEnabled(true);
    }
    else {
        ui->Edit_InputNumberSystem->setDisabled(true);
    }
}

void MainWindow::edit_Input(const QString &text) {
    input_str_ = text;
}

void MainWindow::button_StartTransfer() {
    //ui->lineEdit_Output->clear();

    // check input string
    //if (input_str_.isEmpty() || input_str_.length() < 1) {
    //    qDebug() << "the input str is empty!";
    //}
    //qDebug() << input_str_;
    if (!CheckInput(input_str_))
        return;

    get_NumberSystem();

    switch (number_system_) {
    case NUMBERSYSTEM_BIN:
        Bin2Dec(input_str_,output_str_);
        break;
    case NUMBERSYSTEM_OCT:
        Oct2Dec(input_str_,output_str_);
        break;
    case NUMBERSYSTEM_DEC:
        output_str_ = input_str_;
        break;
    case NUMBERSYSTEM_HEX:
        Hex2Dec(input_str_,output_str_);
        break;
    default:
        break;
    }

    //if (ui->rButton_output_Dec->isChecked())

    if (ui->rButton_output_Bin->isChecked()){
        Dec2Bin(output_str_, output_str_);
    }
    if (ui->rButton_output_Oct->isChecked()) {
        Dec2Oct(output_str_, output_str_);
    }
    if (ui->rButton_output_Hex->isChecked()) {
        Dec2Hex(output_str_, output_str_);
    }
    ui->lineEdit_Output->setText(output_str_);
}

bool MainWindow::CheckInput(QString in)
{
    QString title;
    QString info;

    QString test_bin = "01";
    QString test_oct = "01234567";
    QString test_dec = "0123456789";
    QString test_hex = "0123456789ABCDEF";
    QString test;

    if (in.isEmpty() || in.length() < 1) {
        qDebug() << "the input str is empty!";

        title = "Warning!";
        info = "The input string is empty!";
        QMessageBox::question(this, title, info,
            QMessageBox::Yes,
            QMessageBox::NoButton);

        return false;
    }

    get_NumberSystem();

    switch (number_system_) {
    case NUMBERSYSTEM_BIN:
        info = "The input data is not bin.";
        test = test_bin;
        break;
    case NUMBERSYSTEM_OCT:
        info = "The input data is not oct.";
        test = test_oct;
        break;
    case NUMBERSYSTEM_DEC:
        info = "The input data is not dec.";
        test = test_dec;
        break;
    case NUMBERSYSTEM_HEX:
        info = "The input data is not hex.";
        test = test_hex;
        break;
    }
    int flag = 0;
    for(QChar c : in) {
        //qDebug() << c;
        int flag_test = 0;
        for(QChar j : test) {
            if (c == j)
                flag_test++;
        }
        if (!flag_test) {
            flag++;
        }
    }
    if (flag) {
        title = "Warning!";
        //info = "The input string is not binary!";
        QMessageBox::question(this, title, info,
            QMessageBox::Yes,
            QMessageBox::NoButton);

        return false;
    }

    return true;
}


void MainWindow::Bin2Dec(QString in, QString &out)
{
    long long tmp = 0;
    int size = in.length();
    foreach(QChar c, in) {
        qDebug() << c;
        if (c > '1')
            continue;
        tmp += (c.toLatin1() - '0') * std::pow(2, size - 1);
        size--;
    }
    out = QString::number(tmp);
}

void MainWindow::Oct2Dec(QString in, QString &out)
{
    long long tmp = 0;
    int size = in.length();
    foreach(QChar c, in) {
        qDebug() << c;
        if (c > '8')
            continue;
        tmp += (c.toLatin1() - '0') * std::pow(8, size - 1);
        size--;
    }
    out = QString::number(tmp);
}

void MainWindow::Hex2Dec(QString in, QString &out)
{
    long long tmp = 0;
    int size = in.length();
    foreach(QChar c, in) {
        qDebug() << c;
        if (c > '0' && c < '9')
            tmp += (c.toLatin1() - '0') * std::pow(16, size - 1);
        else if (c >= 'A' && c <= 'F')
            tmp += (c.toLatin1() - 'A' + 10) * std::pow(16, size - 1);
        else
            continue;

        size--;
    }
    out = QString::number(tmp);
}

void MainWindow::Dec2Bin(QString in, QString &out)
{
    std::vector<int> tmp_vector;
    //QString tmp_str;
    long long tmp = in.toLongLong();

    if (tmp == 0) {
        out=QString::number(0);
        return;
    }

    while (tmp) {
        if (tmp % 2)
            tmp_vector.push_back(1);
        else
            tmp_vector.push_back(0);
        tmp /= 2;
    }

    out = "";
    for (auto i = tmp_vector.rbegin();i != tmp_vector.rend();i++) {
        out += QString::number(*i);
    }
}

void MainWindow::Dec2Oct(QString in, QString &out)
{
    std::vector<int> tmp_vector;
    //QString tmp_str;
    long long tmp = in.toLongLong();

    if (tmp == 0) {
        out=QString::number(0);
        return;
    }

    while (tmp) {
        if (tmp % 8)
            tmp_vector.push_back(tmp % 8);
        else
            tmp_vector.push_back(0);
        tmp /= 8;
    }

    out = "";
    for (auto i = tmp_vector.rbegin();i != tmp_vector.rend();i++) {
        out += QString::number(*i);
    }
}

void MainWindow::Dec2Hex(QString in, QString &out)
{
    std::vector<int> tmp_vector;
    //QString tmp_str;
    long long tmp = in.toLongLong();

    if (tmp == 0) {
        out=QString::number(0);
        return;
    }

    while (tmp) {
        if (tmp % 16)
            tmp_vector.push_back(tmp % 16);
        else
            tmp_vector.push_back(0);
        tmp /= 16;
    }

    out = "";
    for (auto i = tmp_vector.rbegin();i != tmp_vector.rend();i++) {
        switch (*i) {
        case 10:
            out += "A";
            break;
        case 11:
            out += "B";
            break;
        case 12:
            out += "C";
            break;
        case 13:
            out += "D";
            break;
        case 14:
            out += "E";
            break;
        case 15:
            out += "F";
            break;
        default:
            out += QString::number(*i);
        }
        //out += QString::number(*i);
    }
}

void MainWindow::N2Dec(QString in, QString &out)
{

}

void MainWindow::Dec2N(QString in, QString &out)
{

}
